Data for Life: Tracking ORT Access for the World’s Most Vulnerabl

1 A Story of Care and Resilience

In a world often captivated by cutting-edge medical breakthroughs, it’s easy to overlook the quiet, lifesaving power of something as simple as a spoonful of salt and sugar mixed into clean water. Diarrhoea remains one of the leading causes of death among children under the age of five, especially in low-income regions. The tragedy lies not only in the illness itself, but in the heartbreaking reality that the treatment — Oral Rehydration Therapy (ORT) — is widely known, incredibly effective, and profoundly affordable. Despite this, millions of children still go without it, due to barriers such as poverty, misinformation, and fragile healthcare systems. This report brings those hidden struggles into view, not through individual stories, but through global data that represents the lives of real children, families, and frontline workers. Within these visuals, you’ll uncover patterns of progress, areas of inequity, and the undeniable impact of community health efforts. Behind every percentage point lies a child who might have lived — or did — because of this humble solution. This is more than a data analysis; it’s a story of resilience, equity, and the collective power to save lives — one sip at a time.

Show/Hide Code
import polars as pl
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import geopandas as gpd
import statsmodels.api as sm
from plotly.subplots import make_subplots

try:
    diarrhoea_df = pl.read_csv("cleaned_data_1_no_null.csv")
    metadata_df = pl.read_csv("cleaned_data_0_no_null.csv")
except FileNotFoundError as e:
    print(f"Error loading data files: {e}")
    print("Please ensure both CSV files are in the working directory")
    exit()


sample_df = diarrhoea_df.to_pandas()

df = diarrhoea_df.join(
    metadata_df,
    on=["country"],
    how="inner"
).filter(
    (pl.col("sex") == "Total") &
    (pl.col("time_period") == pl.col("year"))
)
pdf = df.to_pandas()
pdf = pdf.sort_values("time_period")

2 Key Indicators of Global Diarrhoea Treatment Efforts

Show/Hide Code
import plotly.graph_objects as go

avg_obs = sample_df['obs_value'].mean()

fig1 = go.Figure(go.Indicator(
    mode="number",
    value=avg_obs,
    number={'valueformat': '.1f', 'font': {'size': 50, 'color': '#81c784'}},
    title={"text": "Average ORT Coverage (%)", 'font': {'size': 20}}
))
fig1.update_layout(height=300, margin=dict(t=40, b=10, l=10, r=10))
fig1.show()
Show/Hide Code
record_count = sample_df.shape[0]

fig2 = go.Figure(go.Indicator(
    mode="number",
    value=record_count,
    number={'font': {'size': 50, 'color': '#81c784'}},
    title={"text": "Total Data Points", 'font': {'size': 20}}
))
fig2.update_layout(height=300, margin=dict(t=40, b=10, l=10, r=10))
fig2.show()
Show/Hide Code
distinct_countries = sample_df['country'].nunique()

fig3 = go.Figure(go.Indicator(
    mode="number",
    value=distinct_countries,
    number={'font': {'size': 50, 'color': '#81c784'}},
    title={"text": "Countries Analyzed", 'font': {'size': 20}}
))
fig3.update_layout(height=300, margin=dict(t=40, b=10, l=10, r=10))
fig3.show()

3 Patterns, Progress, and Pain Points

3.2 2. Bar Chart: ORT Treatement by Gender

Show/Hide Code
import plotly.graph_objects as go


countries = sample_df["country"].unique()
fig_bars = go.Figure()


color_map = {
    "Male": "rgba(22,128,60, 0.7)",
    "Female": "rgba(179,225,173,255)",
    "Total": "rgba(0,103,42,255)"
}

#
for country in countries:
    df_filtered = sample_df[sample_df["country"] == country]
    df_latest = df_filtered[df_filtered["time_period"] == df_filtered["time_period"].max()]
    
    fig_bars.add_trace(go.Bar(
        x=df_latest["sex"],
        y=df_latest["obs_value"],
        name=country,
        visible=(country == countries[0]),
        marker=dict(color=[color_map.get(sex, "rgba(44, 160, 44, 0.7)") for sex in df_latest["sex"]]),
        width=0.3  
    ))


buttons = [
    dict(
        label=country,
        method="update",
        args=[
            {"visible": [c == country for c in countries]},
            {"title.text": f"{country}"}
        ]
    )
    for country in countries
]

fig_bars.update_layout(
    updatemenus=[
        dict(
            buttons=buttons,
            direction="down",
            showactive=False,
            x=1.05,
            xanchor="left",
            y=1.0,
            yanchor="top",
            pad={"r": 4, "t": 4},
            font=dict(size=12)
        )
    ],
    title={"text": f" {countries[0]}", "x": 0.5},
    xaxis_title="Gender",
    yaxis_title="% Receiving ORT",
    template="plotly_white",
    bargap=0.2,
    barmode='group'
)

fig_bars.show()
Equal Treatment, Promising Progress

Global data shows near-identical ORT treatment rates for boys and girls with diarrhea, with girls slightly ahead in recent years—a significant achievement in health equity. This parity reflects successful interventions ensuring equal access to this life-saving care. While treatment rates are balanced, subtle differences may persist in prevention and follow-up. The equal bars represent real progress, proving that when simple, effective solutions are prioritized, gender gaps in basic healthcare can be closed. However, continued focus is needed to maintain and expand this equity across all aspects of child health

3.3 3. Trend Over Time for Selected Country

Show/Hide Code
import plotly.express as px
import plotly.graph_objects as go

df_total = sample_df[sample_df["sex"] == "Total"]
countries = df_total["country"].unique()

fig = go.Figure()


pattern_shapes = ["x", "/", "\\", ".", "+"]
green_transparent = "rgba(0, 128, 0, 0.3)"  

for i, country in enumerate(countries):
    df_country = df_total[df_total["country"] == country]
    area = px.area(
        df_country,
        x="time_period",
        y="obs_value",
        title=f"ORT Trend Over Time: {country}",
        pattern_shape_sequence=[pattern_shapes[i % len(pattern_shapes)]],
    )
    
    for trace in area.data:
        trace.update(
            line=dict(color="darkgreen", width=1.5),  
            fillcolor=green_transparent,  
            visible=(i == 0)
        )
        fig.add_trace(trace)


buttons = [
    dict(label=country,
         method="update",
         args=[{"visible": [j // 1 == i for j in range(len(countries))]},
               {"title": f"ORT Trend Over Time: {country}"}])
    for i, country in enumerate(countries)
]

fig.update_layout(
    updatemenus=[dict(active=0, buttons=buttons)],
    xaxis_title="Year",
    yaxis_title="ORT Coverage (%)",
    template="plotly_white"
)

fig.show()
This chart tracks how individual countries have progressed over the years in providing ORT. Some nations display a steady rise, reflecting robust policy efforts and health campaigns. Others show erratic patterns or stagnation—signaling disruptions or neglected attention. These country-level insights empower policymakers to replicate success models and re-evaluate faltering initiatives.

3.4 4. Scatter Plot: GDP vs ORT Coverage

Show/Hide Code
fig_gdp_scatter = px.scatter(
    pdf,
    x="GDP per capita (constant 2015 US$)",
    y="obs_value",
    color="country",
    title="GDP per Capita vs ORT Coverage",
    labels={
        "GDP per capita (constant 2015 US$)": "GDP per capita (2015 US$)",
        "obs_value": "% Receiving ORT"
    }
)

X = pdf[["GDP per capita (constant 2015 US$)"]]
X = sm.add_constant(X)
y = pdf["obs_value"]
model = sm.OLS(y, X).fit()
pdf["regression"] = model.predict(X)

fig_gdp_scatter.add_traces(go.Scatter(
    x=pdf["GDP per capita (constant 2015 US$)"],
    y=pdf["regression"],
    mode="lines",
    name="Regression Line",
    line=dict(color="black", dash="dot")
))

fig_gdp_scatter.update_layout(template="plotly_white")
fig_gdp_scatter.show()
This scatter plot connects economic prosperity with health outcomes. Countries with higher GDP per capita generally show higher ORT coverage, revealing how economic strength often enables better health infrastructure. Yet, some lower-income countries outperform richer peers, showing that political will and targeted health initiatives can drive impact—regardless of financial constraints.

4 More to Look At

Show/Hide Code
from IPython.display import display, HTML
latest_year = metadata_df["year"].max()


latest_data = metadata_df.filter(pl.col("year") == latest_year)

columns_needed = [
    "country",
    "Population, total",
    "GDP per capita (constant 2015 US$)",
    "Life expectancy at birth, total (years)",
    "GDP growth (annual %)"
]

latest_data = latest_data.select(columns_needed)


html_code = """
<div style="display: flex; overflow-x: auto; padding: 20px; gap: 1.5rem; scroll-snap-type: x mandatory;">
"""

for row in latest_data.iter_rows(named=True):
    country = row["country"]
    population = f"{row['Population, total']:,}" if row['Population, total'] else "N/A"
    gdp_per_capita = f"${row['GDP per capita (constant 2015 US$)']:,.2f}" if row['GDP per capita (constant 2015 US$)'] else "N/A"
    life_expectancy = f"{row['Life expectancy at birth, total (years)']:.1f} years" if row['Life expectancy at birth, total (years)'] else "N/A"
    gdp_growth = f"{row['GDP growth (annual %)']:.2f}%" if row['GDP growth (annual %)'] else "N/A"

    html_code += f"""
        <div style="
            flex: 0 0 auto;
            width: 300px;
            height: 260px;
            background: rgba(227, 227, 227, 0.08);
            border-radius: 10px;
            box-shadow: 0 7px 15px rgba(0,0,0,0.2);
            display: flex;
            flex-direction: column;
            align-items: left;
            justify-content: center;
            font-family: 'Poppins', 'Segoe UI', 'Roboto', sans-serif;
            scroll-snap-align: center;
            padding: 20px;
            text-align: left;
            transition: transform 0.3s ease;
            backdrop-filter: blur(5px);
            overflow: hidden;
            word-wrap: break-word;
            white-space: normal;
            overflow-wrap: break-word;
        "
        onmouseover="this.style.transform='scale(1.05)';" 
        onmouseout="this.style.transform='scale(1)';"
        >
        <div style="flex: 1; display: flex; align-items: left; justify-content: left;">
        <h2 style="font-size: 24px; font-weight: 600;">{country}</h2>
    </div>

    <!-- RIGHT SIDE: KPIs -->
    <div style="flex: 2; display: flex; flex-direction: column; justify-content: center;">
        <p><strong>GDP: </strong>{gdp_per_capita}</p>
        <p><strong>Population: </strong>{population}</p>
        <p><strong>Life Expectancy: </strong>{life_expectancy}</p>
        <p><strong>Growth Rate: </strong>{gdp_growth}</p>
    </div>
    </div>
    """

html_code += "</div>"


display(HTML(html_code))

Australia

GDP: $56,739.03

Population: 23,815,995.0

Life Expectancy: 82.4 years

Growth Rate: 2.19%

Austria

GDP: $43,915.23

Population: 8,642,699.0

Life Expectancy: 81.2 years

Growth Rate: 1.30%

Belgium

GDP: $40,893.80

Population: 11,274,196.0

Life Expectancy: 81.0 years

Growth Rate: 1.47%

Canada

GDP: $43,594.19

Population: 35,704,498.0

Life Expectancy: 81.8 years

Growth Rate: 0.65%

Chile

GDP: $13,433.92

Population: 18,047,625.0

Life Expectancy: 79.7 years

Growth Rate: 2.15%

Czech Republic

GDP: $17,931.60

Population: 10,546,059.0

Life Expectancy: 78.6 years

Growth Rate: 4.96%

Denmark

GDP: $53,094.01

Population: 5,683,483.0

Life Expectancy: 80.7 years

Growth Rate: 2.10%

Estonia

GDP: $17,722.16

Population: 1,315,407.0

Life Expectancy: 77.6 years

Growth Rate: 1.84%

Finland

GDP: $42,560.35

Population: 5,479,531.0

Life Expectancy: 81.5 years

Growth Rate: 0.47%

France

GDP: $36,702.43

Population: 66,548,272.0

Life Expectancy: 82.3 years

Growth Rate: 1.07%

Germany

GDP: $41,911.01

Population: 81,686,611.0

Life Expectancy: 80.6 years

Growth Rate: 1.65%

Greece

GDP: $17,980.73

Population: 10,820,883.0

Life Expectancy: 81.0 years

Growth Rate: -0.23%

Hungary

GDP: $12,717.04

Population: 9,843,028.0

Life Expectancy: 75.6 years

Growth Rate: 3.71%

Ireland

GDP: $64,311.82

Population: 4,701,957.0

Life Expectancy: 81.5 years

Growth Rate: 24.62%

Israel

GDP: $36,123.99

Population: 8,380,100.0

Life Expectancy: 82.1 years

Growth Rate: 2.31%

Italy

GDP: $30,387.13

Population: 60,730,582.0

Life Expectancy: 82.5 years

Growth Rate: 0.89%

Japan

GDP: $34,960.64

Population: 127,141,000.0

Life Expectancy: 83.8 years

Growth Rate: 1.56%

South Korea

GDP: $28,737.44

Population: 51,014,947.0

Life Expectancy: 82.0 years

Growth Rate: 2.81%

Luxembourg

GDP: $105,462.01

Population: 569,604.0

Life Expectancy: 82.3 years

Growth Rate: 2.27%

Mexico

GDP: $10,021.24

Population: 121,072,306.0

Life Expectancy: 74.7 years

Growth Rate: 2.70%

Netherlands

GDP: $45,793.81

Population: 16,939,923.0

Life Expectancy: 81.5 years

Growth Rate: 2.12%

New Zealand

GDP: $38,639.35

Population: 4,609,400.0

Life Expectancy: 81.6 years

Growth Rate: 3.73%

Norway

GDP: $74,809.97

Population: 5,188,607.0

Life Expectancy: 82.3 years

Growth Rate: 1.86%

Poland

GDP: $12,637.52

Population: 37,986,412.0

Life Expectancy: 77.5 years

Growth Rate: 4.43%

Portugal

GDP: $19,215.78

Population: 10,358,076.0

Life Expectancy: 81.1 years

Growth Rate: 1.59%

Slovakia

GDP: $16,442.08

Population: 5,423,801.0

Life Expectancy: 76.6 years

Growth Rate: 5.18%

Slovenia

GDP: $20,697.27

Population: 2,063,531.0

Life Expectancy: 80.8 years

Growth Rate: 2.39%

Spain

GDP: $25,969.84

Population: 46,444,832.0

Life Expectancy: 82.8 years

Growth Rate: 4.06%

Sweden

GDP: $51,197.95

Population: 9,799,186.0

Life Expectancy: 82.2 years

Growth Rate: 4.41%

Switzerland

GDP: $83,806.45

Population: 8,282,396.0

Life Expectancy: 82.9 years

Growth Rate: 1.64%

Turkey

GDP: $11,050.00

Population: 78,218,479.0

Life Expectancy: 76.6 years

Growth Rate: 6.08%

United Kingdom

GDP: $44,964.39

Population: 65,116,219.0

Life Expectancy: 81.0 years

Growth Rate: 2.22%

United States

GDP: $57,040.21

Population: 320,738,994.0

Life Expectancy: 78.7 years

Growth Rate: 2.95%

4.1 5. Range of ORT Coverage Over Time

Show/Hide Code
import plotly.graph_objects as go


range_df = sample_df.groupby("time_period")["obs_value"].agg(['min', 'max']).reset_index()
range_df["trend"] = (range_df["min"] + range_df["max"]) / 2


gradient_color = "rgba(0, 128, 0, 0.3)" 


fig_range = go.Figure([
    
    go.Scatter(x=range_df["time_period"], y=range_df["max"],
               mode="lines", name="Max", line=dict(width=0)),

    
    go.Scatter(x=range_df["time_period"], y=range_df["min"],
               fill='tonexty', fillcolor=gradient_color,
               mode="lines", name="Min", line=dict(width=0)),

    
    go.Scatter(x=range_df["time_period"], y=range_df["trend"],
               mode="lines", name="Trend", line=dict(color="green", width=2))
])

fig_range.update_layout(
    title="Range of ORT Coverage Over Time",
    xaxis_title="Year",
    yaxis_title="ORT Coverage (%)",
    template="plotly_white"
)

fig_range.show()
This graph uncovers the global range of ORT coverage each year—illustrating both progress and disparity. While the overall trend is upward, the persistent gap between highest and lowest coverage points to deep-rooted inequality. Bridging this gap demands international cooperation and localized intervention strategies that reach the most vulnerable.

5 Conclusion

This report provides insights into diarrhoea treatment across nations and its relationship with economic and healthcare factors.